package com.crdeng.system.security;

import com.alibaba.fastjson.JSONArray;
import com.crdeng.handler.BusinessException;
import com.crdeng.response.ResultCode;
import com.crdeng.system.vo.UserRoleVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JwtUtils {


    public static final String TOKEN_HEADER = "token";
    public static final String token_prefix = "Bearer ";

    private static final String SUBJECT = "crdeng";

    private static final long EXPIRITION = 1000 * 24 * 60 * 60 * 7;

    private static final String APPSECRET_KEY = "mayikt_secret";  //盐

    private static final String ROLE_CLAIMS = "roles";

    public static String generateJsonWebToken(UserRoleVO user) {
        String token = Jwts
                .builder()
                .setSubject(SUBJECT)
                .claim(ROLE_CLAIMS, user.getAuthorities())
                .claim("id", user.getId())
                .claim("username", user.getUsername())
                .setIssuedAt(new Date()) //签发时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION)) //过期时间
                .signWith(SignatureAlgorithm.HS256, APPSECRET_KEY).compact(); //签名算法以及密匙
        return token;
    }

    /**
     * 生成token
     *
     * @param username
     * @param role
     * @return
     */
    public static String createToken(String username, String role) {

        Map<String, Object> map = new HashMap<>();
        map.put(ROLE_CLAIMS, role);

        String token = Jwts
                .builder()
                .setSubject(username)
                .setClaims(map)
                .claim("username", username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, APPSECRET_KEY).compact();
        return token;
    }

    public static UserRoleVO checkJWT(String token) {
        try {
            Claims claims = parseJwt(token);
            String username = claims.get("username").toString();
            long id = Long.parseLong(claims.get("id").toString());
            UserRoleVO userRoleVO = new UserRoleVO();
            userRoleVO.setId(id);
            userRoleVO.setUsername(username);
            return  userRoleVO;
        } catch (Exception e) {
            e.printStackTrace();
            throw  new BusinessException(ResultCode.USER_ACCOUNT_EXPIRED.getCode(),ResultCode.USER_ACCOUNT_EXPIRED.getMessage());
        }

    }

    //不管是否过期，都返回claims对象
    public static Claims parseJwt(String token){
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(APPSECRET_KEY) // 设置标识名
                    .parseClaimsJws(token)  //解析token
                    .getBody();
        } catch (ExpiredJwtException e) {
            claims = e.getClaims();
        }
        return claims;
    }



    /**
     * 获取用户名
     *
     * @param token
     * @return
     */
    public static String getUsername(String token) {
        Claims claims = Jwts.parser().setSigningKey(APPSECRET_KEY).parseClaimsJws(token).getBody();
        String username = claims.get("username").toString();

        return  username;

    }

    /**
     * 获取用户角色
     *
     * @param token
     * @return
     */
    public static List<SimpleGrantedAuthority> getUserRole(String token) {
        Claims claims = parseJwt(token);
        List roles = (List) claims.get("roles");
        String json = JSONArray.toJSONString(roles);
        List<SimpleGrantedAuthority>
                grantedAuthorityList =
                JSONArray.parseArray(json, SimpleGrantedAuthority.class);

        return grantedAuthorityList;
    }

    /**
     * 是否过期
     *
     * @param token
     * @return
     */
    public static boolean isExpiration(String token) {
        Claims claims = parseJwt(token);
        Date expiration = claims.getExpiration();
        //和当前时间进行对比来判断是否过期
        return new Date(System.currentTimeMillis()).after(expiration);
    }


}
